home *** CD-ROM | disk | FTP | other *** search
Text File | 2001-02-01 | 34.3 KB | 1,247 lines |
- ## -*-Tcl-*-
- # ###################################################################
- # AlphaTcl - core Tcl engine
- #
- # FILE: "coreFixes.tcl"
- # created: 31/7/97 {2:09:16 am}
- # last update: 02/01/2001 {10:28:32 AM}
- # Author: Vince Darley
- # E-mail: <vince@santafe.edu>
- # mail: 317 Paseo de Peralta, Santa Fe, NM 87501
- # www: <http://www.santafe.edu/~vince/>
- #
- # Reorganisation carried out by Vince Darley with much help from Tom
- # Fetherston, Johan Linde and suggestions from the Alpha-D mailing list.
- # Alpha is shareware; please register with the author using the register
- # button in the about box.
- #
- # This file contains Tcl procs which wrap around or replace
- # core (hard-coded) Alpha procs to fix some bugs they may have.
- # Sadly most core Alpha bugs can't be fixed in this way.
- #
- # Ultimately, one hopes, these bugs will be fixed and these procs
- # can be removed...
- # ###################################################################
- ##
-
- # ◊◊◊◊ Buggy procs ◊◊◊◊ #
-
- if {[info exists alpha::gotCoreFixes]} {
- return
- }
-
- if {[info tclversion] < 8.0} {
- # Replicates some of the functionality of Tcl 8's 'foreach' command.
- proc newforeach {vars vals script} {
- set _for_index 0
- while {$_for_index < [llength $vals]} {
- foreach var $vars {
- set val [lindex $vals $_for_index]
- incr _for_index
- uplevel 1 [list set $var $val]
- }
- uplevel 1 $script
- }
- }
- } else {
- # Wrap around Tcl 8's foreach
- proc newforeach {args} { uplevel 1 foreach $args }
- }
-
- if {[info tclversion] < 8.0} {
- proc ensureTextWasColoured {pos t} {
- if {[set nlines [llength [split $t "\r"]]] > 1} {
- goto $pos
- for {set n 2} {$n <= $nlines} {incr n} {
- goto [nextLineStart [getPos]]
- replaceText [getPos] [getPos] ""
- undo
- }
- }
- }
- } else {
- # We'll fix this in Alpha 8
- proc ensureTextWasColoured {pos t} {}
- }
-
-
- namespace eval status {}
- if {[info commands status::flash] == ""} {
- proc status::flash {color} {
- # not implemented
- }
- }
-
- if {[info commands status::msg] == ""} {
- # 'message' conflicts with Tk, so we should gradually transition
- # away from that to 'status::msg'.
- proc status::msg {text} {
- message $text
- }
- }
-
- if {[info tclversion] < 8.0} {
- proc status::prompt {args} {
- set opts(-add) key
- getOpts {-command -add -appendvar}
- switch -- [llength $args] {
- default {
- error "status::prompt ?-f -add what -command script -appendvar var?\
- prompt ?oldfunc? ?add?"
- }
- 1 {
- set prompt [lindex $args 0]
- set func ""
- }
- 2 {
- newforeach {prompt func} $args {}
- }
- 3 {
- newforeach {prompt func opts(-add)} $args {}
- }
- }
- if {[info exists opts(-f)]} {
- status::flash black
- }
- global status::proc status::add status::oldstyle
- if {[info exists func] && [string length $func]} {
- set status::oldstyle 1
- } else {
- set func $opts(-command)
- set status::oldstyle 0
- }
- set status::proc $func
- set status::add $opts(-add)
-
- set thePrompt $prompt
- while {1} {
- set err [catch [list uplevel [list statusPrompt $thePrompt status::helper]] res]
- # tclLog "\r$err $res"
- if {$err == 1} {
- if {$res == ""} {
- # Assume a backspace
- uplevel [list status::helper "" "\010"]
- # Since we are going to re-enter 'statusPrompt, we have to
- # adjust the initial prompt to display the current search string.
- if {[info exists opts(-appendvar)]} {
- upvar $opts(-appendvar) pat
- set thePrompt "${prompt}${pat}"
- } else {
- set thePrompt $prompt
- }
- continue
- }
- }
- return -code $err $res
- }
- }
-
- proc status::helper {args} {
- global status::add status::proc status::oldstyle
- switch -- ${status::add} {
- "modifiers" -
- "anything" {
- lappend args [getModifiers]
- }
- }
- if {${status::oldstyle}} {
- return [uplevel 1 ${status::proc} $args]
- } else {
- return [uplevel 1 ${status::proc} [lrange $args 1 end]]
- }
- }
- } else {
- ##
- # -------------------------------------------------------------------------
- #
- # "status::prompt" --
- #
- # This is a more useful and generally more powerful replacement for the
- # built in 'statusPrompt'. It gives the caller more control and
- # flexibility about a variety of actions (especially 'delete' keys),
- # while trying to place as little burden on the caller as possible.
- #
- # If you wish to query modifier key presses too, the current getModifier
- # key status can be appended to the command script too.
- #
- # There are basically two ways of calling this procedure:
- #
- # (i) old style 'status::prompt ?-f? promptText ?promptFunc? ?add?'
- #
- # see the documentation of statusPrompt for this case; it is very
- # similar. The given function is called with a few arguments appended,
- # the old string, the new char, and possibly the getModifier status.
- #
- # (ii) new style 'status::prompt ?-f? ?-add what? ?-command script? prompt'
- #
- # In this case, the command script is expected to keep track of the
- # current prompt, and so the command script is evaluated with only 1 or 2
- # arguments appended: the new character pressed, and optional the getModifier
- # status.
- #
- # An optional -debug flag can be used to 'tclLog' the command lines used,
- # and results from calling the command script.
- #
- # For compatibility with Alphatk, you must not call 'getModifiers' yourself,
- # but should use the optional '-add' argument. ('-add anything' is usual).
- #
- # -------------------------------------------------------------------------
- ##
- proc status::prompt {args} {
- set opts(-add) key
- getOpts {-command -add -appendvar}
- switch -- [llength $args] {
- default {
- error "status::prompt ?-f -add what -command script -appendvar var?\
- prompt ?oldfunc? ?add?"
- }
- 1 {
- set prompt [lindex $args 0]
- set func ""
- }
- 2 {
- foreach {prompt func} $args {}
- }
- 3 {
- foreach {prompt func opts(-add)} $args {}
- }
- }
- if {[info exists opts(-f)]} {
- status::flash black
- }
- if {[info exists func] && [string length $func]} {
- set oldstyle 1
- } else {
- set func $opts(-command)
- set oldstyle 0
- }
- set thePrompt $prompt
- message $thePrompt
- set statuscontents ""
- while {1} {
- if {!$oldstyle} {
- set statuscontents ""
- }
- set res [coreKeyPrompt $thePrompt]
- set args {}
- if {$oldstyle} {
- lappend args $statuscontents
- }
- lappend args [lindex $res 0]
- switch -- $opts(-add) {
- "modifiers" -
- "anything" {
- lappend args [lindex $res 1]
- }
- }
- if {[info exists opts(-debug)]} {
- tclLog "$func $args"
- }
- if {[set err [catch [list uplevel 1 $func $args] res]]} {
- if {[info exists opts(-debug)]} {
- global errorInfo
- tclLog "$err $res $errorInfo"
- }
- return -code $err $res
- }
- if {$oldstyle} {
- if {[info exists opts(-debug)]} {
- tclLog "Returned: $res"
- }
- if {$res == ""} {
- return $statuscontents
- }
- }
- if {[info exists opts(-appendvar)]} {
- upvar $opts(-appendvar) pat
- set thePrompt "${prompt}${pat}"
- } else {
- set thePrompt $prompt
- if {$oldstyle} {
- append statuscontents $res
- message "$thePrompt$statuscontents"
- }
- }
- }
- }
- # Alpha 8 has 'betterStatusPrompt' which is both simpler and far more robust.
- if {[info commands coreKeyPrompt] == ""} {
- proc coreKeyPrompt {thePrompt} {
- set err [catch [list betterStatusPrompt $thePrompt] res]
- if {!$err} {
- lappend args [lindex $res 1] [getModifiers]
- return $args
- } else {
- if {[lindex $res 0] == 1} {
- return -code $err "mouse click"
- } else {
- return -code $err [lindex $res 0]
- }
- }
- }
- }
- }
-
- # so any selections present are maintained
- rename centerRedraw __centerRedraw
- ;proc centerRedraw {args} {
- lappend selectionEndPoints [getPos] [selEnd]
- uplevel __centerRedraw $args
- eval select $selectionEndPoints
- }
-
- proc winIsFile {name} {
- return [expr {[file exists $name] || \
- ([regsub { <[0-9]+>$} $name {} name] && [file exists $name])}]
- }
-
- if {![llength [info commands placeText]]} {
- proc placeText {pos text args} {
- if {$pos == "-w"} {
- set w $text
- set pos [lindex $args 0]
- set text [lindex $args 1]
- lappend selectionEndPoints [getPos -w $w] [selEnd -w $w]
- replaceText -w $w $pos $pos $text
- eval select -w [list $w] $selectionEndPoints
- } else {
- lappend selectionEndPoints [getPos] [selEnd]
- replaceText $pos $pos $text
- eval select $selectionEndPoints
- }
- }
- }
-
- # so any selections present are maintained
- rename insertToTop __insertToTop
- ;proc insertToTop {args} {
- lappend selectionEndPoints [getPos] [selEnd]
- uplevel __insertToTop $args
- eval select $selectionEndPoints
- }
-
- # not really a 'fix', but it's much more efficient in many places if
- # you can set the mode of a window in advance ---- else you switch
- # modes twice on opening the window! This version of 'new' has a new
- # flag '-m' which lets you set the mode. It also returns the name
- # of the window which was really opened. Any additional flags received
- # by this proc are assumed to be arguments to be passed to 'setWinInfo',
- # except without the leading '-'. So, for instance you can do:
- # new -n "blah" -tabsize 4 -shell 1
- # Also args '-text' to set the text, or a useful new flag '-info'
- # which takes the text as the next arg, and automatically sets the
- # window to a read-only shell window, and scrolls to the top after
- # inserting the given text. Useful for all those 'info' windows Alpha
- # uses!
- rename new __new
- ;proc new {args} {
- set i 0
- set where {}
- while {[set arg [lindex $args $i]] != ""} {
- incr i
- switch -- $arg {
- "-n" {
- set name [lindex $args $i]
- incr i
- }
- "-g" {
- eval lappend where "-g" [lrange $args $i [incr i 3]]
- incr i
- }
- "-m" {
- set mode [lindex $args $i]
- set mi $i
- incr i
- }
- default {
- set other($arg) [lindex $args $i]
- incr i
- }
- }
- }
- if {![info exists name]} {
- set name "Untitled"
- }
- if {[info tclversion] < 8.0} {
- # Alpha can't cope with colons in names
- regsub -all : $name . name
- }
- set newname $name
-
- if {[lsearch -exact [winNames] $name] != -1} {
- set i 2
- while {[lsearch -exact [winNames] "$name <$i>"] != -1} {
- incr i
- }
- append name " <${i}>"
- }
- if {![info exists mode]} {
- set mode [win::FindMode $newname]
- }
- # This will handle a mode-specific tab size, provided
- # Alpha 8/tk call winCreatedHook at the appropriate time.
- win::setInitialMode $name $mode
-
- if {[info tclversion] < 8.0} {
- # In this section, we want to see if we need to temporally shadow out
- # the global tabSize value with another value so as to avoid having to
- # monkey with the winInfo array after the creation of the window
- global tabSize ${mode}modeVars global::_oldTabSize
- if {[info exists other(-tabsize)]} {
- set global::_oldTabSize $tabSize
- set tabSize $other(-tabsize)
- unset other(-tabsize)
- } elseif {[info exists ${mode}modeVars(tabSize)]} {
- # The mode that the new window will open up in
- # has its own value tabSize
- set global::_oldTabSize $tabSize
- set tabSize [set ${mode}modeVars(tabSize)]
- }
- } else {
- if {[info exists other(-tabsize)]} {
- win::setInitialConfig $name tabsize $other(-tabsize)
- }
- }
-
- global alpha::platform
- if {${alpha::platform} != "alpha"} {
- eval __new -n [list $name] $where
- } else {
- eval __new -n [list $newname] $where
- }
- if {![info exists mode]} {
- set name [win::Current]
- }
- if {[info exists other(-info)]} {
- setWinInfo -w $name shell 1
- insertText $other(-info)
- setWinInfo -w $name read-only 1
- goto [minPos]
- unset other(-info)
- }
- # We must do shell first, then text, then dirty and then others
- # in any order. Else we'd get errors like can't make window read-only
- # when dirty if they were in the wrong order...
- if {[info exists other(-shell)]} {
- setWinInfo -w $name shell $other(-shell)
- unset other(-shell)
- }
- if {[info exists other(-text)]} {
- insertText $other(-text)
- unset other(-text)
- }
- if {[info exists other(-dirty)]} {
- setWinInfo -w $name dirty $other(-dirty)
- unset other(-dirty)
- }
- if {[info exists other]} {
- foreach a [array names other] {
- setWinInfo -w $name [string range $a 1 end] $other($a)
- }
- }
- return $name
- }
-
- # Not really a fix, but adds features much needed by glob, which otherwise
- # force one to write nasty code. Vince's C implementation of this is
- # now in the core of Tcl (8.3 or newer).
-
- ##
- # ------------------------------------------------------------------
- #
- # "glob" --
- #
- # Backwards compatible extensions to the 'glob' command to address
- # some current issues:
- #
- # 'file join' is incompatible with backslash-quoted directory paths,
- # so it is very difficult to deal with paths containing
- # glob-sensitive characters in a cross-platform way. E.g. the user
- # selects a directory in a directory-chooser, and I wish to find (i)
- # all html files in that directory; (ii) all html files in any
- # sub-directory of that directory; (iii) all subdirectories of that
- # directory which contain the word 'hello'. With the new glob, this
- # can be achieved in a simple, cross-platform way as follows:
- #
- # (i)
- #
- # set dir [tk_chooseDirectory]
- # set html_files [glob -dir $dir *.html]
- #
- # (ii)
- #
- # set dir [tk_chooseDirectory]
- # set sub_dir_html_files [glob -join -dir $dir * *.html]
- #
- # (iii)
- #
- # set dir [tk_chooseDirectory]
- # set sub_dirs [glob -types d -dir $dir *hello*]
- #
- # These will work even if '$dir' contains []{}*+\? characters,
- # which would be difficult to achieve using the old glob, without
- # explicit backslash quoting of 'dir', and without explicit use of
- # the current platform's directory separator (':' on MacOS,
- # backslash or forward slash on other platforms). Using this
- # version of glob has allowed me to simplify otherwise messy code,
- # and remove bugs caused by user-selected paths containing bad
- # characters.
- #
- # Syntax:
- #
- # glob ?switches? name ?name ...?
- #
- # Switches:
- #
- # -nocomplain: if no files are found, return an empty string, rather
- # than signal an error.
- #
- # -join: the remaining 'name' arguments are treated as
- # a path specification to be handled with 'file
- # join'.
- #
- # -dir <pat>: search for patterns starting in this directory
- #
- # -path <path>: search for patterns starting with this path
- # prefix (i.e. a directory and a file prefix).
- #
- # -types <list of types>: only list files/directories of one of
- # the types listed. Currently only type 'd' is
- # supported, which lists only directories (hence
- # avoiding the need to specify a platform specific
- # separator char), but in the future, more types
- # (possibly platform specific) will be supported:
- # e.g. on MacOS types such as 'TEXT', 'APPL' will be
- # supported. Unrecognised types are ignored by glob.
- #
- # -- signals the end of switches, even if the next
- # argument starts with a '-'.
- #
- # Each name argument is handled separately, unless '-join' is
- # present. Note the the '-dir' and '-path' flags are mutually
- # exclusive.
- #
- # The Tcl version below should work with Tcl8.0 or newer. It
- # requires a helper procedure 'getOpts' which follows. Obviously if
- # it meets with general approval it should be re-implemented in C.
- #
- # --Version--Author------------------Changes-----------------------
- # 1.0 vince@biosgroup.com original
- # -----------------------------------------------------------------
- ##
- if {[info tclversion] >= 8.0} {
- # Tcl 8.3 or newer have a more complex glob already.
- if {[info tclversion] < 8.3} {
- # we've copied this here from stringsLists.tcl to avoid some
- # bad auto-loading problems if there are early startup errors.
- ;proc getOpts {{take_value ""} {set "set"}} {
- upvar args a
- upvar opts o
- while {[string match \-* [set arg [lindex $a 0]]]} {
- set a [lreplace $a 0 0]
- if {$arg == "--"} {
- return
- } else {
- if {[set idx [lsearch -regexp $take_value \
- "^-?[string range $arg 1 end]( .*)?$"]] == -1} {
- set o($arg) 1
- } else {
- if {[llength [set the_arg \
- [lindex $take_value $idx]]] == 1} {
- $set o($arg) [lindex $a 0]
- set a [lreplace $a 0 0]
- } else {
- set numargs [expr {[lindex $the_arg 1] -1}]
- $set o($arg) [lrange $a 0 $numargs]
- set a [lreplace $a 0 $numargs]
- }
- }
- }
- }
- }
- rename glob __glob
- ;proc glob {args} {
- getOpts {-tails -t -types -type -dir -path}
- # place platform specific file separator in variable 'separator's
- regexp {Z(.)Z} [file join Z Z] "" separator
- if {[info exists opts(-join)]} {
- unset opts(-join)
- set args [list [eval file join $args]]
- }
- set add ""
- foreach t {t type} {
- if {[info exists opts(-$t)]} {
- eval lappend opts(-types) $opts(-$t)
- unset opts(-$t)
- }
- }
- if {[info exists opts(-types)]} {
- if {[set item [lsearch -exact $opts(-types) "d"]] != -1} {
- set opts(-types) [lreplace $opts(-types) $item $item]
- set add $separator
- set isdirectory 1
- }
- }
- if {[set nocomplain [info exists opts(-nocomplain)]]} {
- unset opts(-nocomplain)
- }
- if {[info exists opts(-path)]} {
- if {[info exists opts(-dir)]} {
- if {$nocomplain} {
- return ""
- } else {
- error "Can't use option '-dir' with '-path'"
- }
- }
- regsub -all {[][*?\{\}\\]} $opts(-path) {\\&} prefix
- unset opts(-path)
- } elseif {[info exists opts(-dir)]} {
- regsub -all {[][*?\{\}\\]} $opts(-dir) {\\&} prefix
- append prefix ${separator}
- unset opts(-dir)
- } else {
- set prefix ""
- }
- set res {}
- foreach arg $args {
- eval lappend res [__glob -nocomplain -- \
- "${prefix}${arg}${add}"]
- }
- if {[info exists opts(-types)]} {
- # we ignore arguments to -types which haven't yet been
- # handled, since they are assumed to be platform
- # specific
- unset opts(-types)
- }
- if {[set llen [llength [array names opts]]]} {
- set ok "-nocomplain, -join, -dir <dir>,\
- -path <path>, -types <list of types>"
- if {$llen > 1} {
- error "bad switches \"[array names opts]\":\
- must be $ok or --"
- } else {
- error "bad switch \"[array names opts]\":\
- must be $ok or --"
- }
- } elseif {[llength $res]} {
- if {[info exists isdirectory]} {
- foreach r $res {
- lappend newres [string trimright $r $separator]
- }
- return $newres
- } else {
- return $res
- }
- } elseif {$nocomplain} {
- return ""
- } else {
- switch -- [llength $args] {
- 0 {
- error "wrong # args: should be \"glob ?switches?\
- name ?name ...?\""
- }
- 1 {
- error "no files matched glob pattern \"$args\""
- }
- default {
- error "no files matched glob patterns \"$args\""
- }
- }
- }
- }
- }
-
- } else {
- # we've copied this here from stringsLists.tcl to avoid some
- # bad auto-loading problems if there are early startup errors.
- ;proc getOpts {{take_value ""} {set "set"}} {
- upvar args a
- upvar opts o
- while {[string match \-* [set arg [lindex $a 0]]]} {
- set a [lreplace $a 0 0]
- if {$arg == "--"} {
- return
- } else {
- if {[set idx [lsearch -regexp $take_value \
- "^-?[string range $arg 1 end]( .*)?$"]] == -1} {
- set o($arg) 1
- } else {
- if {[llength [set the_arg \
- [lindex $take_value $idx]]] == 1} {
- $set o($arg) [lindex $a 0]
- set a [lreplace $a 0 0]
- } else {
- set numargs [expr {[lindex $the_arg 1] -1}]
- $set o($arg) [lrange $a 0 $numargs]
- set a [lreplace $a 0 $numargs]
- }
- }
- }
- }
- }
- rename glob __glob
- ;proc glob {args} {
- getOpts {-tails -t -types -type -dir -path}
- # place platform specific file separator in variable 'separator's
- regexp {Z(.)Z} [file join Z Z] "" separator
- if {[info exists opts(-join)]} {
- unset opts(-join)
- set args [list [eval file join $args]]
- }
- set add ""
- foreach t {t type} {
- if {[info exists opts(-$t)]} {
- eval lappend opts(-types) $opts(-$t)
- unset opts(-$t)
- }
- }
- if {[info exists opts(-types)]} {
- if {[set item [lsearch -exact $opts(-types) "d"]] != -1} {
- set opts(-types) [lreplace $opts(-types) $item $item]
- set add $separator
- set isdirectory 1
- }
- }
- if {[set nocomplain [info exists opts(-nocomplain)]]} {
- unset opts(-nocomplain)
- }
- if {[info exists opts(-path)]} {
- if {[info exists opts(-dir)]} {
- if {$nocomplain} {
- return ""
- } else {
- error "Can't use option '-dir' with '-path'"
- }
- }
- if {[regexp {^(\.|:)} $opts(-path)]} {
- set opts(-path) "[pwd][string range $opts(-path) 1 end]"
- }
- regsub -all {[][*?\{\}\\]} $opts(-path) {\\&} prefix
- unset opts(-path)
- } elseif {[info exists opts(-dir)]} {
- if {[regexp {^(\.|:)} $opts(-dir)]} {
- set opts(-dir) [string trimright [pwd][string range $opts(-dir) 1 end] ":"]
- }
- regsub -all {[][*?\{\}\\]} $opts(-dir) {\\&} prefix
- append prefix ${separator}
- unset opts(-dir)
- } else {
- set prefix ""
- }
- set glob_args [list -nocomplain]
- if {[info exists opts(-types)]} {
- foreach pair $opts(-types) {
- set type [lindex $pair 0]
- if {$type != "" && $type != "*"} {
- if {[string length $type] == 4} {
- lappend glob_args -t $type
- } else {
- lappend old_t $pair
- continue
- }
- }
- if {[llength $pair] > 1} {
- # it's a MacOS 'type crea' pair
- set crea [lindex $pair 1]
- if {$crea != "" && $crea != "*"} {
- if {[string length $crea] == 4} {
- lappend glob_args -c $crea
- } else {
- lappend old_t $pair
- continue
- }
- }
- }
- }
- unset opts(-types)
- if {[info exists old_t]} {
- set opts(-types) $old_t
- }
- }
- set res {}
- foreach arg $args {
- eval lappend res [eval __glob $glob_args -- \
- [list "${prefix}${arg}${add}"]]
- }
- if {[info exists opts(-types)]} {
- # we ignore arguments to -types which haven't yet been
- # handled, since they are assumed to be platform specific
- unset opts(-types)
- }
- if {[set llen [llength [array names opts]]]} {
- set ok "-nocomplain, -join, -dir <dir>,\
- -path <path>, -types <list of types>"
- if {$llen > 1} {
- error "bad switches \"[array names opts]\":\
- must be $ok or --"
- } else {
- error "bad switch \"[array names opts]\":\
- must be $ok or --"
- }
- } elseif {[llength $res]} {
- if {[info exists isdirectory]} {
- foreach r $res {
- lappend newres [string trimright $r $separator]
- }
- return $newres
- } else {
- return $res
- }
- } elseif {$nocomplain} {
- return ""
- } else {
- switch -- [llength $args] {
- 0 {
- error "wrong # args: should be \"glob ?switches?\
- name ?name ...?\""
- }
- 1 {
- error "no files matched glob pattern \"$args\""
- }
- default {
- error "no files matched glob patterns \"$args\""
- }
- }
- }
- }
- }
-
- # If the position to blink is offscreen, show a message with context
- rename blink __blink
- ;proc blink {pos} {
- __blink $pos
- getWinInfo w
- if {[info exists w(currline)]} {
- set topl $w(currline)
- set endl [expr {$topl + $w(linesdisp)}]
- scan [posToRowCol $pos] "%d %d" row col
- if {$row < $topl || $row >= $endl} {
- message "Matching '[getText [lineStart $pos] [pos::math $pos + 1]]'"
- }
- }
- }
-
- if {[info tclversion] >= 8.0} {
- # This will work with Alpha 7, although at the expense of changing
- # the file dialog somewhat, so we deactivate it there. You can simply
- # copy this into your prefs.tcl if you want to use it with Alpha 7.
- proc findFile {args} {
- set filename [eval [list getfile "Open which file:"] $args]
- edit $filename
- }
- }
-
- if {[set alpha::platform] == "alpha"} {
- if {[info commands edit] == ""} {
- ;proc edit {args} {
- set resize 0
- set marksMenuOnly 0
-
- set newWinAsk 1
- set readOnlyAsk 1
- set wrapAsk 1
-
- set parameters {}
-
- set i 0
- while {[set arg [lindex $args $i]] != ""} {
- switch -- $arg {
- "-tabsize" {
- set tabsize [lindex $args [incr i]]
- set args [lreplace $args [expr {$i-1}] $i]
- incr i -1
- }
- "-c" {
- set newWinAsk 0
- lappend parameters NewW no
- set args [lreplace $args $i $i]
- }
- "-g" {
- set resize 1
- set left [lindex $args [incr i]]
- set top [lindex $args [incr i]]
- set width [lindex $args [incr i]]
- set height [lindex $args [incr i]]
- set args [lreplace $args [expr {$i-4}] $i]
- incr i -4
- }
- "-m" {
- set marksMenuOnly 1
- }
- "-r" {
- set readOnlyAsk 0
- lappend parameters perm no
- set args [lreplace $args $i $i]
- }
- "-w" {
- set wrapAsk 0
- lappend parameters Wrap no
- set args [lreplace $args $i $i]
- }
- "--" {
- set args [lreplace $args $i $i]
- break
- }
- default {
- break
- }
- }
- }
-
- if {$newWinAsk} {
- lappend parameters NewW ask
- }
- if {$readOnlyAsk} {
- lappend parameters perm ask
- }
- if {$wrapAsk} {
- lappend parameters Wrap ask
- }
-
- if {[set path [lindex $args $i]] == ""} {
- error "No file name specified for edit"
- }
-
- lappend parameters ---- [tclAE::build::alis $path]
-
- eval tclAE::send -s -dr aevt odoc $parameters
-
- if {[info exists tabsize]} {
- setWinInfo tabsize $tabsize
- }
-
- if {$resize} {
- moveWin $left $top
- sizeWin $width $height
- }
-
- if {$marksMenuOnly} {
- setWinInfo marksMenuOnly 1
- }
- }
- } else {
- rename edit __edit
- ;proc edit {args} {
- set i 0
- while {[set arg [lindex $args $i]] != ""} {
- incr i
- switch -- $arg {
- "-tabsize" {
- set tabsize [lindex $args $i]
- set args [lreplace $args [expr {$i-1}] $i]
- incr i
- }
- }
- }
- if {[info exists tabsize]} {
- global tabSize
- set oldTabSize $tabSize
- set tabSize $tabsize
- # So we don't mangle the global tabSize
- set err [catch [list uplevel 1 __edit $args] res]
- set tabSize $oldTabSize
- return -code $err $res
- } else {
- uplevel 1 __edit $args
- }
- }
- }
-
- # keep window vertical position the same
- rename revert __revert
- if {[info tclversion] < 8.0} {
- ;proc revert {args} {
- if {[llength $args] && [lindex $args 0] == "-w"} {
- set win [lindex $args 1]
- getWinInfo -w $win w
- set topl $w(currline)
- bringToFront $win
- uplevel __revert [lrange $args 2 end]
- revertHook $win
- display -w $win [rowColToPos -w $win $topl 0]
- } else {
- getWinInfo w
- set topl $w(currline)
- uplevel __revert $args
- revertHook [win::Current]
- display [rowColToPos $topl 0]
- }
- }
- } else {
- ;proc revert {args} {
- if {[llength $args] && [lindex $args 0] == "-w"} {
- set win [lindex $args 1]
- } else {
- set win [win::Current]
- }
- getWinInfo -w $win w
- set topl $w(currline)
- uplevel __revert $args
- revertHook $win
- display -w $win [rowColToPos -w $win $topl 0]
- }
- }
- if {[info tclversion] < 8.0} {
- # Works around the silly default of 3000 chars internal to Alpha
- rename matchIt __matchIt
- ;proc matchIt {args} {
- if {[llength $args] == 2} {
- # even though the extra argument is a number of characters
- # we simply use maxPos because this is at least as big a
- # number as we need.
- lappend args [maxPos]
- }
- uplevel 1 __matchIt $args
- }
- }
- }
-
- rename edit editDocument
-
- ##
- # -------------------------------------------------------------------------
- #
- # "edit" --
- #
- # This is the start of the chain of events which AlphaTcl expects when
- # Alpha/Alphatk is asked to 'open' a file. That request may result
- # in the file being opened, or, depending on procedures registered
- # with 'editHook', a different action may be taken. For example,
- # installer files should avoid the whole 'edit' completely, non-text
- # files could be ignored, and even more complex actions could be taken.
- # For example, with the appropriate Tcl extensions, we can arrange for
- # the mounting of 'virtual file systems' (such as .tar, .sit or .zip
- # files) when the archive is opened by Alpha (hence allowing transparent
- # editing of their contents in place). Even urls could be mounted in
- # this way to provide an alternative method of editing files on remote
- # ftp sites.
- #
- # Anyway, procedures registered to editHook should return 0
- # if they took no action, or 1 if they accept resposibility for the
- # file. No other return values are permitted. The 'mode' field
- # of this hook is the file's extension.
- #
- # Extensions must be lowercase (in the hook::register call). For
- # example:
- #
- # hook::register editHook install::editHook .install
- #
- # In the future we will integrate this with the above implementations
- # of edit so that we can, for instance, specify a flag to force Alpha
- # to edit the file.
- # -------------------------------------------------------------------------
- ##
- proc edit {args} {
- set filename [lindex $args end]
- if {![hook::callUntil editHook \
- [string tolower [file extension $filename]] $filename]} {
- eval editDocument $args
- }
- }
-
-
-
- namespace eval menu {}
- rename insertMenu __insertMenu
- rename removeMenu __removeMenu
- ;proc insertMenu {m} {
- global menu::toplevels
- __insertMenu $m
- set menu::toplevels($m) 1
- }
- ;proc removeMenu {m} {
- global menu::toplevels
- __removeMenu $m
- set menu::toplevels($m) 0
- }
-
- proc menu::inserted {m} {
- global menu::toplevels
- if {[info exists menu::toplevels($m)]} {
- return [set menu::toplevels($m)]
- } else {
- return 0
- }
- }
-
- rename save __save
- ;proc save {{name ""}} {
- global win::Modified win::Active
- if {$name == ""} {
- set name [lindex [set win::Active] 0]
- } elseif {[info tclversion] < 8.0} {
- bringToFront $name
- }
- set origName $name
- if {![file exists $name] && \
- !([regsub { <[0-9]+>$} $name {} name] && [file exists $name])} {
- if {[info exists win::Modified($origName)]} {
- if {![dialog::yesno "The file appears to have been moved\
- since it was last opened or saved. Are you sure you\
- want to save it?"]} {
- error "Save aborted by user, since file appears to\
- have been moved."
- }
- }
- # It's a new window which has never been saved
- set isNew 1
- } else {
- getFileInfo $name info
- if {[info tclversion] < 8.0} {
- # We used the 'red disk icon' to save, which doesn't
- # call savePostHook. We could call savePostHook now,
- # except that it could cause some weird problems if
- # any registered hooks do things the user only expects
- # to happen immediately after a save.
- if {![info exists win::Modified($origName)]} {
- set win::Modified($origName) $info(modified)
- }
- }
- if {[set win::Modified($origName)] < $info(modified)} {
- # File has changed on disk
- if {![dialog::yesno "This file has changed on disk. Are you\
- sure you want to save it?"]} {
- error "Save aborted by user, since newer file existed."
- }
- }
- }
- if {[info tclversion] >= 8.0} {
- uplevel 1 [list __save $origName]
- } else {
- uplevel 1 __save
- # New windows don't get savePostHook called until Alpha 8, so
- # we have to do it manually
- if {[info exists isNew]} {
- # The user may have cancelled the save
- set name [win::Current]
- if {[file exists $name] || \
- ([regsub { <[0-9]+>$} $name {} name] && [file exists $name])} {
- savePostHook [win::Current]
- }
- }
- }
- }
-
-
- rename print __print
- ;proc print {args} {
- # make sure we've got our procs loaded, else Alpha can't print
- auto_load printLeftHeader
- auto_load printRightHeader
- if {[llength $args]} {
- if {[catch [list __print [lindex $args 0]]]} {
- file::openQuietly [lindex $args 0]
- bringToFront [lindex $args 0]
- uplevel __print
- }
- } else {
- uplevel __print
- }
- }
-
- # Fixes two bugs: the message in the status window was incorrect (shows
- # the search, not replace string). Also a replace string of nothing was
- # rejected.
- if {[llength [info commands enterReplaceString]]} {rename enterReplaceString ""}
- ;proc enterReplaceString {} {
- set t [getSelect]
- replaceString $t
- message "Entered replace '$t'"
- }
- # Doesn't fix any bugs, but forces enterSearchString to use the
- # command 'searchString' rather than setting the string behind
- # the scenes.
- if {[llength [info commands enterSearchString]]} {rename enterSearchString ""}
- ;proc enterSearchString {} {
- set t [getSelect]
- searchString $t
- message "Entered search '$t'"
- }
-
-
- # ◊◊◊◊ Procs fixed in Alpha 8 ◊◊◊◊ #
-
- if {[info tclversion] >= 8.0} {
- # We just have this proc to help people who haven't updated their code
- # to use Tcl 8's native routines. It will vanish eventually.
- ;proc mkdir {dir} {
- file mkdir $dir
- }
- return
- }
-
- rename saveAs __saveAs
- ;proc saveAs {args} {
- uplevel __saveAs $args
- savePostHook [win::Current]
- }
-
- # old version is a bit picky
- if {![string length [info commands __cd]]} {
- rename cd __cd
- }
- ;proc cd args {
- if {$args == ".."} { set args "::" }
- if {$args == "."} { set args ":" }
- if {[llength $args]} {
- set path [string trim [eval list $args] " \{\}"]
- if {![regexp {:$} $path]} { append path ":" }
- if {![file isdirectory $path] && [file isdirectory [pwd]$path]} {
- set path ":$path"
- }
- __cd $path
- } else {
- global HOME
- __cd $HOME
- }
- }
-
- # fix for Alpha trapping command clicks on lines which contain ':'
- # unnecessarily.
- rename icURL __icURL
- ;proc icURL {args} {
- if {[regexp "^f(ile|tp)::" $args] || [catch {eval __icURL $args}]} {
- set mods [getModifiers]
- # Alpha highlights the wrong piece of text, so find mouse pos
- # and generate a new piece position
- if {![catch {mousePos} pos]} {
- goto [eval rowColToPos $pos]
- }
- cmdDoubleClick -1 -1 \
- [expr {$mods & 34}] [expr {$mods & 72}] [expr {$mods & 144}]
- }
- }
- # bring to front does nothing if already foremost
- # (the original calls activateHook, changeMode....)
- rename bringToFront __bringToFront
- ;proc bringToFront {name} {
- global win::Current
- if {[file tail $name] != [file tail ${win::Current}]} {
- __bringToFront $name
- }
- }
-
- # if you select a directory from inside it, it has a ':', if you select
- # from outside, it doesn't have a colon. There is another problem, which
- # is that Alpha won't let you select a volume, only a folder within a
- # volume, but I haven't fixed that here.
- rename get_directory __get_directory
- ;proc get_directory {args} {
- set dir [eval __get_directory $args]
- regsub {:$} $dir {} dir
- return $dir
- }
-
-
- # Setting fonts and tabs doesn't need to dirty the window
- rename setFontsTabs __setFontsTabs
- ;proc setFontsTabs {args} {
- set d [winDirty]
- uplevel __setFontsTabs $args
- if {!$d && [winDirty]} {
- setWinInfo dirty 0
- }
- }
-
- set alpha::gotCoreFixes 1
-